#include "StdAfx.h"
#include "Triplet.h"

namespace SpikingNeuronLib
{
	Triplet::Triplet(array<FiringEvent>^ events)
	{
		this->_triplet = gcnew List<FiringEvent>(events);
	}

	Triplet::Triplet(FiringEvent event1, FiringEvent event2, FiringEvent event3)
	{
		this->_triplet = gcnew List<FiringEvent>(3);

		this->_triplet->Add(event1);
		this->_triplet->Add(event2);
		this->_triplet->Add(event3);
	}

	bool Triplet::IsEquivalent(Triplet^ otherTriplet)
	{
		array<int>^ first = Enumerable::ToArray<int>(this->Transpose()->FiringTimes);
		array<int>^ second = Enumerable::ToArray<int>(otherTriplet->Transpose()->FiringTimes);

		return Enumerable::SequenceEqual<int>(first, second);
	}

	int Triplet::CompareTo(Object^ other)
	{
		//if (other->GetType() == Triplet::typeid)
		Triplet^ otherTriplet = (Triplet^) other;

		Tuple<int, int, int, int, int, int>^ first = this->AsSixTuple;
		Tuple<int, int, int, int, int, int>^ second = otherTriplet->AsSixTuple;

		return ((IComparable^) first)->CompareTo(second);
	}

	Triplet^ Triplet::Transpose()
	{
		array<FiringEvent>^ events = gcnew array<FiringEvent>(3);

		int firstFiring = Enumerable::Min(this->FiringTimes);
		for (int i = 0; i < _triplet->Count; i++)
		{
			events[i] = FiringEvent(_triplet[i].Time - firstFiring, _triplet[i].NeuronIndex, _triplet[i].Label);
		}

		return gcnew Triplet(events);
	}

	System::Collections::Generic::HashSet<int>^ Triplet::GetFuzzyFiringTimes(int jitter)
	{
		HashSet<int>^ fuzzy1 = _triplet[0].GetFuzzyFiringTime(jitter);
		HashSet<int>^ fuzzy2 = _triplet[1].GetFuzzyFiringTime(jitter);
		HashSet<int>^ fuzzy3 = _triplet[2].GetFuzzyFiringTime(jitter);

		fuzzy1->UnionWith(fuzzy2);
		fuzzy1->UnionWith(fuzzy3);

		return fuzzy1;
	}

	String^ Triplet::ToString()
	{
		using namespace System::Text;
		StringBuilder^ sb = gcnew StringBuilder();
		for (int i = 0; i < _triplet->Count; i++)
		{
			sb->Append(_triplet[i].ToString());
			if (i < _triplet->Count - 1)
				sb->Append(", ");
		}

		return sb->ToString();
	}
}